#include "cheetah/graphics/cube_texture_gl.h"

#include "cheetah/core/error.h"
#include "cheetah/graphics/cube_image.h"
#include "cheetah/graphics/image.h"
#include "cheetah/graphics/utils.h"

namespace cheetah {
namespace graphics {
using namespace core;
CubeTextureGL::~CubeTextureGL(void) {	this->Release(); }

void CubeTextureGL::Bind(void) const {
  if (0 == tex_id_) {
    Error("'CubeTextureGL::Bind', invalid texture");
    return;
  }
  glBindTexture(GL_TEXTURE_CUBE_MAP, tex_id_);
}

void CubeTextureGL::Unbind(void) const {
  if (0 == tex_id_) {
    Error("'CubeTextureGL::Bind', invalid texture");
    return;
  }
  GLint current_id = 0;
  glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &current_id);
  if (tex_id_ != current_id) {
    Error("'CubeTextureGL::Bind', texture not bound");
    return;
  }
  glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}

void CubeTextureGL::SetDefaultParameters(void) {
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
}

bool CubeTextureGL::BeginInitialize(void) {
  if (0 != tex_id_) {
    Error("'CubeTextureGL::BeginInitialize', texture already initialized!"); 
    return false;
  }
  if (CheckErrorsGL("CubeTextureGL::BeginInitialize")) return false;
  glGenTextures(1, &tex_id_);
  glBindTexture(GL_TEXTURE_CUBE_MAP, tex_id_);
  this->SetDefaultParameters();
  if (CheckErrorsGL("CubeTextureGL::BeginInitialize")) return false;
  return true;
}

bool CubeTextureGL::EndInitialize(void) {
  glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  if (CheckErrorsGL("CubeTextureGL::EndInitialize")) {
    this->Release();
    return false;
  }

  return true;
}

bool CubeTextureGL::Initialize(int width, int height, GLint internal_format) {
  if (!BeginInitialize()) return false; 
  for (int i = 0; i < 6; ++i) {
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, 
                 width, height, 0, 0, 0, NULL);
  }
  return EndInitialize();	
}

bool CubeTextureGL::Initialize(const CubeImage &image, GLint internal_format) {
  if (!BeginInitialize()) return false;
  for (int i = 0; i < 6; ++i) {
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, 
                 image.width(), image.height(), 0, image.format(), 
                 image.type(), image.data(i));
  }
  return EndInitialize();	
}

bool CubeTextureGL::Initialize(Image *images[6], GLuint internal_format) {
  if (!BeginInitialize()) return false;
  for (int i = 0; i < 6; ++i) {
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format,
                 images[i]->width(), images[i]->height(), 0, 
                 images[i]->format(), images[i]->type(), images[i]->data());
  }
  return EndInitialize();
}

void CubeTextureGL::Release(void) {
  if (tex_id_ > 0) {
    glDeleteTextures(1, &tex_id_);
    tex_id_ = 0;
  }
}

} // graphics
} // cheetah
